﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GRAPHANLib;
using LEMMATIZERLib;
using AGRAMTABLib;
using SYNANLib;
using MAPOSTLib;
using System.Runtime.ExceptionServices;

namespace OffLineFilter
{
    public class SyntaxHolder
    {
        public const int RussianLanguage = 1;
        public const int CoverageKillHomonyms = 1;

        public bool ResolveHomonyms { get; set; }

        public SyntaxHolder(bool resolveHomonyms)
        {
            ResolveHomonyms = resolveHomonyms;
        }

        private IGraphmatFile graphan;
        protected IGraphmatFile Graphan
        {
            get
            {
                if (graphan == null)
                {
                    graphan = new GraphmatFile();
                    graphan.Language = RussianLanguage;
                    graphan.LoadDicts();
                }
                return graphan;
            }
        }

        private ILemmatizer lemmatizer;
        protected ILemmatizer Lemmatizer
        {
            get
            {
                if (lemmatizer == null)
                {
                    lemmatizer = new LemmatizerRussian();
                    lemmatizer.LoadDictionariesRegistry();
                }
                return lemmatizer;
            }
        }

        private IGramTab gramtab;
        protected IGramTab Gramtab
        {
            get
            {
                if (gramtab == null)
                {
                    gramtab = new RusGramTab();
                    gramtab.Load();
                }
                return gramtab;
            }
        }

        private IMAPost mapost;
        protected IMAPost Mapost
        {
            get
            {
                if (mapost == null)
                {
                    mapost = new MAPost();
                    mapost.Init(RussianLanguage, Lemmatizer, Gramtab);
                }
                return mapost;
            }
        }

        private ISentencesCollection sentencesCollection;
        protected ISentencesCollection SentencesCollection
        {
            get
            {
                if (sentencesCollection == null)
                {
                    sentencesCollection = new SentencesCollection();
                    sentencesCollection.SyntaxLanguage = RussianLanguage;
                    sentencesCollection.SetLemmatizer(Lemmatizer);
                    sentencesCollection.KillHomonymsMode = CoverageKillHomonyms;
                    sentencesCollection.InitializeProcesser();
                }
                return sentencesCollection;
            }
        }

        private List<Sentence> sentences;
        public List<Sentence> Sentences
        {
            get { return sentences; }
        }

        [HandleProcessCorruptedStateExceptionsAttribute]
        public bool ProcessText(String str)
        {
            try
            {
                IPLMLineCollection afterMorph = new PLMLineCollection();
                afterMorph.AttachLemmatizer(Lemmatizer);
                SentencesCollection.ClearSentences();
                Graphan.LoadStringToGraphan(str);

                afterMorph.ProcessHyphenWords(Graphan);
                afterMorph.ProcessPlmLines(Graphan);
                Graphan.FreeTable();

                IPLMLineCollection beforeSyntax = afterMorph;
                if (ResolveHomonyms)
                    beforeSyntax = Mapost.ProcessData(afterMorph);

                SentencesCollection.ProcessData(beforeSyntax);
                afterMorph.Clear();
                beforeSyntax.Clear();

                Cache();
            }
            catch { return false; }
            return true;
        }

        public void Cache()
        {
            List<Word> words = new List<Word>();
            for (int i = 0; i < SentencesCollection.SentencesCount; i++)
            {
                IEnumerable<IWord> iwords = SentencesCollection.Sentence[i].GetWords();
                words = words.Concat(iwords.Select(iword => new Word()
                {
                    Lemma = iword.Homonym[0].Lemma,
                    Pos = iword.Homonym[0].POSStr,
                    CommonGrammems = iword.Homonym[0].CommonGrammemsStr,
                    GramDescription = iword.Homonym[0].GramDescriptionStr
                })).ToList();
            }

            if (sentences == null)
                sentences = new List<Sentence>();
            sentences.Add(new Sentence() { Words = words });
        }
    }
}
